#include <math.h>
#include "rcore.h"
#include "stateManager.h"
#include "state.h"
#include "InputManager.h"
#include "RenderObject.h"

template<> RenderCore* gcore::Singleton<RenderCore>::ms_Singleton = 0;

RenderCore::RenderCore()
{
	hge = 0;

	x=100.0f;
	y=100.0f;
	dx=0.0f;
	dy=0.0f;

	speed=50;
	friction=0.98f;


}

RenderCore::~RenderCore()
{
//	if (fnt) delete fnt;
//	if (hge) delete hge;
}

void RenderCore::init()
{
    // Get HGE interface
    hge = hgeCreate(HGE_VERSION);

    // Set up log file, frame function, render function and window title
    hge->System_SetState(HGE_LOGFILE, "ITGJP.log");
    hge->System_SetState(HGE_FRAMEFUNC, staticFrameFunc);
    hge->System_SetState(HGE_RENDERFUNC, staticRenderFunc);
    hge->System_SetState(HGE_TITLE, "ITGJP!!");

    // Set up video mode
    hge->System_SetState(HGE_WINDOWED, true);
    hge->System_SetState(HGE_SCREENWIDTH, 800);
    hge->System_SetState(HGE_SCREENHEIGHT, 600);
    hge->System_SetState(HGE_SCREENBPP, 32);
}

HWND RenderCore::GetHWND()
{
	return hge->System_GetState(HGE_HWND);
}

bool RenderCore::staticRenderFunc()
{
	return RenderCore::getSingleton().RenderFunc();
}

bool RenderCore::staticFrameFunc()
{
	return StateManager::getSingletonPtr()->GetState()->FrameFunc();
	//return RenderCore::getSingleton().FrameFunc();
}

void RenderCore::Shutdown()
{
	hge->System_Shutdown();
    hge->Release();
}

bool RenderCore::Start()
{
    if(hge->System_Initiate())
    {
		//********setup the input manager here********//
		InputManager *mInputManager = InputManager::getSingletonPtr();
		mInputManager->initialise( GetHWND() );

		//Setup the listeners to listen to the StateManager
		mInputManager->addKeyListener( StateManager::getSingletonPtr(), "Keyboard" );
		mInputManager->addMouseListener( StateManager::getSingletonPtr(), "Mouse" );
		mInputManager->addJoystickListener( StateManager::getSingletonPtr(), "Joystick" );


        // Load sound and texture
        snd=hge->Effect_Load("menu.wav");
        //quad.tex=hge->Texture_Load("particles.png");
        fnt=new hgeFont("font1.fnt");
        fnt->SetColor(0xFFFFFFFF);

        if(!snd) // || !quad.getQuad().tex)
        {
            // If one of the data files is not found, display
            // an error message and shutdown.
            MessageBox(NULL, "Can't load MENU.WAV", "Error", MB_OK | MB_ICONERROR | MB_APPLMODAL);
            hge->System_Shutdown();
            hge->Release();
            return 0;
        }

        // Set up quad which we will use for rendering sprite
        //quad.blend=BLEND_ALPHAADD | BLEND_COLORMUL | BLEND_ZWRITE;
/*
        for(int i=0;i<4;i++)
        {
            // Set up z-coordinate of vertices
            quad.v[i].z=0.5f;
            // Set up color. The format of DWORD col is 0xAARRGGBB
            quad.v[i].col=0xFFFFA000;
        }

        // Set up quad's texture coordinates.
        // 0,0 means top left corner and 1,1 -
        // bottom right corner of the texture.
        quad.v[0].tx=96.0/128.0; quad.v[0].ty=64.0/128.0;
        quad.v[1].tx=128.0/128.0; quad.v[1].ty=64.0/128.0;
        quad.v[2].tx=128.0/128.0; quad.v[2].ty=96.0/128.0;
        quad.v[3].tx=96.0/128.0; quad.v[3].ty=96.0/128.0;
*/
        // Let's rock now!
        hge->System_Start();

        // Free loaded texture and sound
        //hge->Texture_Free(quad.tex);
        hge->Effect_Free(snd);
//        delete fnt;
    }
    else MessageBox(NULL, hge->System_GetErrorMessage(), "Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);

    return true;
}

void RenderCore::boom()
{
    int pan=int((x-400)/4);
    float pitch=(dx*dx+dy*dy)*0.0005f+0.2f;
    hge->Effect_PlayEx(snd,100,pan,pitch);
}

bool RenderCore::FrameFunc()
{
	/*
    float dt=hge->Timer_GetDelta();

    if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true;
    if (hge->Input_GetKeyState(HGEK_A)) dx-=speed*dt;
    if (hge->Input_GetKeyState(HGEK_D)) dx+=speed*dt;
    if (hge->Input_GetKeyState(HGEK_W)) dy-=speed*dt;
    if (hge->Input_GetKeyState(HGEK_S)) dy+=speed*dt;

    int key = hge->Input_GetKey();
    if (key == HGEK_SUBTRACT) speed-=1;
    if (key == HGEK_ADD) speed+=1;

    dx*=friction; dy*=friction; x+=dx; y+=dy;

    if(x>784) {x=784-(x-784);dx=-dx;boom();}
    if(x<16) {x=16+16-x;dx=-dx;boom();}
    if(y>584) {y=584-(y-584);dy=-dy;boom();}
    if(y<16) {y=16+16-y;dy=-dy;boom();}

    quad.v[0].x=x-16; quad.v[0].y=y-16;
    quad.v[1].x=x+16; quad.v[1].y=y-16;
    quad.v[2].x=x+16; quad.v[2].y=y+16;
    quad.v[3].x=x-16; quad.v[3].y=y+16;
    */
    return false;

}

bool RenderCore::RenderFunc()
{
	int count = 0;

    hge->Gfx_BeginScene();
    hge->Gfx_Clear(0);

    std::vector<RenderObject*>::iterator i;
    for ( i = objList.begin(); i != objList.end(); i++)
    {
    	count ++;
		hge->Gfx_RenderQuad(&(*i)->getQuad());
    }

    fnt->printf(5,5,HGETEXT_LEFT,"Speed:%f\nQuads:%d", (sqrt(dx*dx+dy*dy)), count);
    hge->Gfx_EndScene();

    return false;
}

bool RenderCore::registerObj( RenderObject *obj )
{
	objList.push_back(obj);
	return true;
}

unsigned int RenderCore::getWidth()
{
	return hge->System_GetState(HGE_SCREENWIDTH);
}

unsigned int RenderCore::getHeight()
{
	return hge->System_GetState(HGE_SCREENHEIGHT);
}

unsigned int RenderCore::getDepth()
{
	return hge->System_GetState(HGE_SCREENBPP);
}

RenderCore* RenderCore::getSingletonPtr(void)
{
	return ms_Singleton;
}

RenderCore& RenderCore::getSingleton(void)
{
	assert(ms_Singleton);
	return *ms_Singleton;
}
